#ifndef ASSEMBLER_H
#define ASSEMBLER_H
#include "jtypes.h"
#include "SimpleIo.h"
class ConstantPool;

enum {
  OPC_nop=0x00,
  
  OPC_iconst_0=0x03,
  OPC_iconst_1=0x04,
  OPC_iconst_2=0x05,
  OPC_iconst_3=0x06,
  OPC_iconst_4=0x07,
  OPC_iconst_5=0x08,

  OPC_dconst_0=0x0e,
  OPC_dconst_1=0x0f,

  OPC_ldc1=0x12,
  OPC_ldc2=0x13,
  OPC_ldc2w=0x14,
  OPC_iload=0x15,

  OPC_dload=0x18,

  OPC_iload_0=0x1A,
  OPC_iload_1=0x1B,
  OPC_iload_2=0x1C,
  OPC_iload_3=0x1D,

  OPC_dload_0=0x26,
  OPC_dload_1=0x27,
  OPC_dload_2=0x28,
  OPC_dload_3=0x29,

  OPC_dstore=0x39,

  OPC_istore_0=0x3B,
  OPC_istore_1=0x3C,
  OPC_istore_2=0x3D,
  OPC_istore_3=0x3E,

  OPC_dstore_0=0x47,
  OPC_dstore_1=0x48,
  OPC_dstore_2=0x49,
  OPC_dstore_3=0x4a,

  OPC_iadd=0x60,
  OPC_ladd=0x61,
  OPC_fadd=0x62,
  OPC_dadd=0x63,
  OPC_isub=0x64,
  OPC_lsub=0x65,
  OPC_fsub=0x66,
  OPC_dsub=0x67,

  OPC_dmul=0x6b,

  OPC_ddiv=0x6f,

  OPC_dcmpl=0x97,
  OPC_dcmpg=0x98,

  OPC_ifeq=0x99,
  OPC_ifne=0x9a,
  OPC_iflt=0x9b,
  OPC_ifge=0x9c,
  OPC_ifgt=0x9d,
  OPC_ifle=0x9e,

  OPC_goto=0xa7,

  OPC_return=0xB1,
  OPC_getstatic=0xB2,
  OPC_invokevirtual=0xB6,
};

class Assembler 
{
  public:

    Assembler();

    Assembler(FILE *f);

    void disassemble(ConstantPool *cp);

    void save(FILE *f);

    u4   getSize();

    void assemble(u1 opcode, u4 operand);
    void assemble(u1 opcode);

    void assembleAt(u4 offset,u1 opcode, u4 operand);

    void relocAt(u4 offset,u4 targetAddress);

    /*
     */
    void resetCode();

    /* return current assemble pointer
     */
    u4 getAP();

    /* utility function to generate 'enum' from 
     * internal table */
    void generateEnum();

    /* utility function to dump all known 
     * opcodes */
    void dumpOpcodes();
  private:

    void  addByte(unsigned char);


    u1*   code;
    u4    allocated_code;
    u4    first_byte_free;

};

#endif
